package org.testis.gui.mvc.controller.testdesign;

import org.testis.gui.mvc.controller.*;
import org.testis.gui.mvc.model.testdesign.LabelSettingsModel;
import org.testis.gui.mvc.view.labels.DefaultLabelJTree;
import org.testis.gui.mvc.view.labels.DefaultLabelTreeLoader;
import org.testis.gui.mvc.view.labels.ILabelTreeLoader;
import org.testis.gui.mvc.view.labels.LabelSettingsView;
import org.testis.orm.labelhandler.LabelDataHandler;
import org.testis.orm.labelhandler.LabelFactory;
import org.testis.orm.labelhandler.LabelRefined;
import org.testis.utils.tree.DefaultMutableLabelNode;
import javax.swing.JOptionPane;
import javax.swing.tree.TreePath;

import org.testis.utils.tree.LabelTreeNode;

/**
 *
 * @author nurhat
 */
public class LabelSettingsController extends AbstractController {

    public static final String SHOW_VIEW_PROPERTY = "ViewVisibility";
    public static final String TREE_LOAD_PROPERTY = "LoadTree";
    public static final String TREE_REFRESH_PROPERTY = "RefreshTree";
    public static final String SELECTED_NODE_PROPERTY = "SelectedNode";
    public static final String SELECTION_TREE_PATH_PROPERTY = "SelectionTreePath";
    public static final String ERROR_PROPERTY = "LastError";
    private DefaultMutableLabelNode m_treeRoot;

    public LabelSettingsController() {
        super();
        loadLabelTree();
    }

    synchronized public void operationLoadTree(DefaultMutableLabelNode treeNode) {
        setModelProperty(TREE_LOAD_PROPERTY, treeNode);
    }

    public void operationRefreshTree() {
        setModelProperty(TREE_REFRESH_PROPERTY, true);
    }

    public void operationSelectTreePath(TreePath path) {
        if (path != null) {
            setModelProperty(SELECTION_TREE_PATH_PROPERTY, path);
            operationSelectLabel(
                    (DefaultMutableLabelNode) path.getLastPathComponent());
        }
    }

    synchronized public void operationSelectLabel(DefaultMutableLabelNode node) {
        setSelectedLabel(node);
    }

    public void operationStartLoader() {
        initialize();
        operationLoadTree(m_treeRoot);
        setModelProperty(SHOW_VIEW_PROPERTY, true);
    }

    public void operationCloseWindow() {
        super.cleanAll();
    }

    private void setSelectedLabel(DefaultMutableLabelNode node) {
        setModelProperty(SELECTED_NODE_PROPERTY, node);
    }

    private void initialize() {
        LabelSettingsView view = new LabelSettingsView(
                TestDesignControllerList.newInstance().getParentFrame(), true);
        view.pack();
        addView(view);
        addModel(new LabelSettingsModel());
    }

    public boolean operationCheckLabelNameExists(String name) {
        return LabelFactory.newInstance().hasLabel(name);
    }

    public void operationAddLabel(String name) {
        LabelRefined newRefined = LabelFactory.newInstance().createLabel(name);
        if (newRefined != null) {
            DefaultMutableLabelNode parentNode = getSelectedLabelNode();
            DefaultMutableLabelNode newNode = new DefaultMutableLabelNode(new LabelTreeNode(
                    newRefined));
            parentNode.add(newNode);
            operationRefreshTree();
            operationSelectTreePath(new TreePath(newNode.getPath()));
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to add label record...");
        }
    }

    public void operationAddLabel(String name, int containerId) {
        if (name == null || name.trim().equals("")) {
            setModelProperty(ERROR_PROPERTY,
                    "Unable to add label, invalid label name...");
            return;
        }

        if (operationCheckLabelNameExists(name)) {
            setModelProperty(ERROR_PROPERTY,
                    "Label name: '" + name + "' already defined");
            return;
        }

        LabelRefined newRefined = LabelFactory.newInstance().createLabel(name,
                containerId);
        if (newRefined != null) {
            DefaultMutableLabelNode parentNode = getSelectedLabelNode();
            DefaultMutableLabelNode newNode = new DefaultMutableLabelNode(new LabelTreeNode(
                    newRefined));
            parentNode.add(newNode);
            operationRefreshTree();
            operationSelectTreePath(new TreePath(newNode.getPath()));
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to add label");
        }
    }

    public void operationSaveLabel(int id, String name) {
        if (name == null || name.trim().equals("")) {
            setModelProperty(ERROR_PROPERTY,
                    "Unable to edit label, invalid label name");
            return;
        }

        // check that label name already defined
        LabelRefined refined = LabelFactory.newInstance().getLabel(name);
        if (refined != null && refined.getId() != id) {
            setModelProperty(ERROR_PROPERTY,
                    "Label name: '" + name + "' already defined");
            return;
        }

        if (LabelDataHandler.newInstance().saveLabel(id, name)) {
            operationRefreshTree();
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to edit label");
        }
    }

    private void operationRemoveSelectedNode() {
        DefaultMutableLabelNode selectedNode = getSelectedLabelNode();
        operationRemoveNode(selectedNode);
    }

    private void operationRemoveNode(DefaultMutableLabelNode node) {
        if (node != null) {
            node.removeFromParent();
            operationRefreshTree();
        }
    }

    public void operationDeleteLabel(DefaultMutableLabelNode node) {
        if (node == null) {
            setModelProperty(ERROR_PROPERTY, "Unable to delete label...");
            return;
        }

        LabelRefined refined = node.getLabel();
        if (refined == null) {
            setModelProperty(ERROR_PROPERTY, "Unable to delete label...");
            return;
        }

        if (LabelFactory.newInstance().deleteLabel(refined.getId())) {
            operationRemoveNode(node);
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to delete label");
        }
    }

    public void operationDeleteLabel(int id) {
        if (LabelFactory.newInstance().deleteLabel(id)) {
            operationRemoveSelectedNode();
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to delete label");
        }
    }

    public void operationDeleteSelectedLabel() {
        LabelRefined refined = getSelectedLabel();
        if (refined != null) {
            operationDeleteLabel(refined.getId());
        } else {
            setModelProperty(ERROR_PROPERTY, "Unable to delete label");
        }
    }

    public boolean operationCheckIsInUse(int labelId) {
        LabelRefined refined = LabelFactory.newInstance().getLabel(labelId);
        if (refined != null) {
            return refined.hasPair();
        }
        return false;
    }

    private void loadLabelTree() {
        DefaultMutableLabelNode root = getLabelTreeRoot();
        operationLoadTree(root);
    }

    public DefaultMutableLabelNode getLabelTreeRoot() {
        if (m_treeRoot == null) {
            ILabelTreeLoader treeLoader = new DefaultLabelTreeLoader();
            setLabelTreeRoot(treeLoader.loadTree());
        }
        return m_treeRoot;
    }

    public void setLabelTreeRoot(DefaultMutableLabelNode rootNode) {
        m_treeRoot = rootNode;
    }

    public DefaultMutableLabelNode getSelectedLabelNode() {
        return (DefaultMutableLabelNode) getModelProperty(SELECTED_NODE_PROPERTY);
    }

    public LabelRefined getSelectedLabel() {
        DefaultMutableLabelNode selectedNode = getSelectedLabelNode();
        if (selectedNode != null) {
            return selectedNode.getLabel();
        }
        return null;
    }
}
